use chrono::{DateTime, offset::Utc};
use std::time::{Duration};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Bucket {
  pub symbol: String,
  pub close: f32,
  pub timestamp: DateTime<Utc>
}

impl Ord for Bucket {
    fn cmp(&self, other: &Bucket) -> Ordering {
        self.timestamp.cmp(&other.timestamp)
    }
}

impl PartialOrd for Bucket {
    fn partial_cmp(&self, other: &Bucket) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Bucket {
    fn eq(&self, other: &Bucket) -> bool {
        self.timestamp == other.timestamp
    }
}
impl Hash for Bucket {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.timestamp.hash(state);
    }
}

impl Eq for Bucket {}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BucketRequest {
  pub symbol: String,
  pub count: u32
}

#[derive(Debug, Eq, Clone)]
pub struct RateLimitInfo {
  pub remaining_reqs: u32,
  pub retry_after: Option<Duration>,
  pub timestamp: DateTime<Utc>
}

impl Ord for RateLimitInfo {
    fn cmp(&self, other: &RateLimitInfo) -> Ordering {
        self.timestamp.cmp(&other.timestamp)
    }
}

impl PartialOrd for RateLimitInfo {
    fn partial_cmp(&self, other: &RateLimitInfo) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for RateLimitInfo {
    fn eq(&self, other: &RateLimitInfo) -> bool {
        self.timestamp == other.timestamp
    }
}
